﻿using Serilog;
using System;
using System.Collections.Concurrent;
using System.Threading;

namespace Common.Framework.Core.Message
{
    /// <summary>
    /// MessageBus
    /// </summary>
    public class MessageBus : IMessageBus
    {
        private static readonly object _instanceLocker = new object();
        private readonly ConcurrentQueue<IMessage> _messaegPool = new ConcurrentQueue<IMessage>();
        private readonly int POLLING_INTERVAL = 300;
        private readonly Thread _thread;

        private MessageBus()
        {
            _thread = new Thread(Subscribe);
            RunIt();
        }

        public static MessageBus Instance
        {
            get
            {
                return SingletonProxy<MessageBus>.Create(() => new MessageBus());
            }
        }

        private void ProcessMessage(IMessage message)
        {
            try
            {
                //TODO TEST
                throw new InvalidOperationException();
                message.ProcessMe();
            }
            catch (Exception ex)
            {
                Log.Information($"MessageBus:ErrorMessage:{ex}");
                ex.Data["Method"] = "MessageBus/ProcessMessage";
            }
        }

        private void Subscribe()
        {
            while (true)
            {
                try
                {
                    if (_messaegPool.Count > 0)
                    {
                        IMessage message;
                        if (_messaegPool.TryDequeue(out message))
                        {
                            ProcessMessage(message);
                        }
                    }
                    else
                    {
                        Thread.Sleep(POLLING_INTERVAL);
                    }
                }
                catch (Exception ex)
                {
                    Log.Information($"MessageBus:ErrorMessage:{ex}");
                    ex.Data["Method"] = "MessageBus/Subscribe";
                }
            }
        }

        public void Pubish(IMessage message)
        {
            _messaegPool.Enqueue(message);
        }

        public void RunIt()
        {
            _thread.Start();
        }

        public void StopIt()
        {
            throw new NotImplementedException();
        }
    }
}
